/*
 * colourlicprocessor.h
 *
 *  Created on: 17/08/2012
 *      Author: cvan680
 */

#ifndef COLOURLICPROCESSOR_H_
#define COLOURLICPROCESSOR_H_

#include "voreen/core/processors/renderprocessor.h"
#include "voreen/core/properties/optionproperty.h"
#include "modules/flowreen/processors/flowreenprocessor.h"
#include "modules/flowreen/datastructures/simpletexture.h"

#include "voreen/core/ports/renderport.h"
#include "voreen/core/properties/filedialogproperty.h"
#include "voreen/core/properties/vectorproperty.h"
#include "voreen/core/properties/buttonproperty.h"
#include "tgt/shadermanager.h"

namespace voreen {

class ColourLICProcessor : public RenderProcessor, public FlowreenProcessor {
public:
	ColourLICProcessor();

    // virtual constructor
    virtual Processor* create() const;

    // documentary functions
    virtual std::string getClassName() const { return "ColourLICProcessor";       }
    virtual std::string getCategory() const  { return "Image Processing";      }
    virtual CodeState getCodeState() const   { return CODE_STATE_EXPERIMENTAL; }


protected:

    enum SliceAlignment {
    	// :-)
        PLANE_XY = 2,   /** view from the volume's front to back (negative z-axis) */
        PLANE_XZ = 1,   /** view from the volume's bottom to top (negative y-axis) */
        PLANE_ZY = 0    /** view from the volume's right to left (negative x-axis) */
    };

    enum TextureZoom {
        ZOOM_FULL_SIZE = 0,
        ZOOM_1X = 1,
        ZOOM_2X = 2,
        ZOOM_4X = 4,
        ZOOM_8X = 8
    };

    // used to distinguish between return values
    enum LICWarning {
    	ZERO_VECTOR = -1
    };

    enum ComboType {
    	MULTIPLICATION = 0,
    	WEIGHTED_ADDITION = 1
    };


    TextureZoom zoom_;

    virtual void setDescriptions() {
        setDescription("Input 1: vector field, Input 2: scalar field. LIC on field 1, colourmap on field 2.");
    }

    // actual rendering code
    virtual void process();

    /// loads the shader
    virtual void initialize() throw (VoreenException);

    /// frees the shader
    virtual void deinitialize() throw (VoreenException);

private:
    // ports and properties
    //RenderPort inport_;

    // ports
    VolumeCollectionPort inport_;
	VolumePort volPort1_;
	VolumePort volPort2_;
    RenderPort outport_;

    // properties
    // LIC
    FileDialogProperty grammarfile_;
    ButtonProperty update_prop;
    IntProperty kernelSizeProp_;
    IntProperty pixelSamplingProp_;
    BoolProperty useAdaptiveKernelSizeProp_;
    FloatVec2Property thresholdProp_;

    // slice
    OptionProperty<SliceAlignment>* alignmentProp_;
    IntProperty sliceIndexProp_;

    // combo
    OptionProperty<ComboType>* comboProp_;
    FloatProperty weightingFactor_;

    // vars
    /** the current 2D texture containing the flow image */
    tgt::Texture* sliceTexture_;

    /** the currently used slice alignment */
    SliceAlignment alignment_;

    /** permutation of the components of the flow according to selected slice alignment */
    tgt::ivec3 permutation_;

    float getTextureScalingFactor( const tgt::vec2& viewportSize,
                                                  const tgt::vec2& textureSize   );

    float calculateVectorMagnitude( tgt::vec3 v );

    void onThresholdChange();
    void onSliceAlignmentChange();
    tgt::ivec3 getCoordinatePermutation(const SliceAlignment& alignment);


    bool loadShader(const std::string& vertexShaderName, const std::string& fragmentShaderName);
    std::string generateShaderHeader();


	tgt::vec4 getColour(float value);
    float clamp(float value, float min, float max);
    int clamp2(int value, int min, int max);
    tgt::vec3 mix(tgt::vec3 vec1, tgt::vec3 vec2, float fraction);


    tgt::Shader* shader_;

    float* pixels;
    float* colourTexture;
    bool LICchanged;
    void toggleLIC();

    // GLSL shader
    //tgt::Shader* shader_;
};

} // namespace

#endif /* COLOURLICPROCESSOR_H_ */
